www.gusucode.com > VC Treeview控件节点位置任意拖放示例 > VC Treeview控件节点位置任意拖放示例/gusucode/dragView.cpp

    // dragView.cpp : implementation of the CDragView class
//

#include "stdafx.h"
#include "drag.h"

#include "dragDoc.h"
#include "dragView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDragView

IMPLEMENT_DYNCREATE(CDragView, CTreeView)

BEGIN_MESSAGE_MAP(CDragView, CTreeView)
	//{{AFX_MSG_MAP(CDragView)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_DESTROY()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDragView construction/destruction

CDragView::CDragView()
	: m_pDragImage(NULL), 
	  m_htiDrag(NULL), 
	  m_htiDrop(NULL),
	  m_htiOldDrop(NULL),
	  m_bLDragging(false),
	  m_idTimer(0)
{

}

CDragView::~CDragView()
{
}

BOOL CDragView::PreCreateWindow(CREATESTRUCT& cs)
{
	if( CTreeView::PreCreateWindow(cs) == FALSE )
		return FALSE;

	cs.style |= TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT;

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CDragView drawing

void CDragView::OnDraw(CDC* pDC)
{
	CDragDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// TODO: add draw code for native data here
}

void CDragView::OnInitialUpdate()
{
	CTreeView::OnInitialUpdate();

	CTreeCtrl& theTree = GetTreeCtrl();
	
	CImageList* pImage = new CImageList;
	pImage->Create( IDR_IMAGE, 16, 1, ::GetSysColor(COLOR_WINDOW) );
	theTree.SetImageList( pImage, TVSIL_NORMAL );

	TVINSERTSTRUCT insert;
	::ZeroMemory( &insert, sizeof(TVINSERTSTRUCT) );

	TVITEM item;
	::ZeroMemory( &item, sizeof(TVITEM) );

	item.mask = TVIF_IMAGE|TVIF_TEXT;
	item.pszText = "Root Item";
	item.iImage  = 0;
	insert.hParent = TVI_ROOT;
	insert.hInsertAfter = TVI_LAST;
	::CopyMemory( &(insert.item), &item, sizeof(TVITEM) );
	
	HTREEITEM hParent = theTree.InsertItem( &insert );

	item.pszText = "Branch";
	insert.hParent = hParent;
	::CopyMemory( &(insert.item), &item, sizeof(TVITEM) );
	for( int i = 0; i < 10; i++ )
		theTree.InsertItem( &insert );

	item.mask = TVIF_IMAGE|TVIF_TEXT;
	item.pszText = "Root Item";
	item.iImage  = 0;
	insert.hParent = TVI_ROOT;
	insert.hInsertAfter = TVI_LAST;
	::CopyMemory( &(insert.item), &item, sizeof(TVITEM) );

	hParent = theTree.InsertItem( &insert );

	item.pszText = "Branch";
	insert.hParent = hParent;
	::CopyMemory( &(insert.item), &item, sizeof(TVITEM) );
	for( i = 0; i < 10; i++ )
		theTree.InsertItem( &insert );
}

/////////////////////////////////////////////////////////////////////////////
// CDragView diagnostics

#ifdef _DEBUG
void CDragView::AssertValid() const
{
	CTreeView::AssertValid();
}

void CDragView::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}

CDragDoc* CDragView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDragDoc)));
	return (CDragDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDragView message handlers

void CDragView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	m_htiDrag = pNMTreeView->itemNew.hItem;
	m_htiDrop = NULL;

	m_pDragImage = GetTreeCtrl().CreateDragImage( m_htiDrag );
	if( !m_pDragImage )
		return;

	m_bLDragging = true;

	CPoint pt(0,0);
	
	IMAGEINFO ii;
	m_pDragImage->GetImageInfo( 0, &ii );
	pt.x = (ii.rcImage.right - ii.rcImage.left) / 2;
	pt.y = (ii.rcImage.bottom - ii.rcImage.top) / 2;

	m_pDragImage->BeginDrag( 0, pt );
	pt = pNMTreeView->ptDrag;
	ClientToScreen( &pt );
	m_pDragImage->DragEnter(NULL,pt);
	
	SetCapture();

	*pResult = 0;
}

void CDragView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CTreeView::OnLButtonUp(nFlags, point);

	if( m_bLDragging )
	{
		CTreeCtrl& theTree = GetTreeCtrl();

		m_bLDragging = false;

		CImageList::DragLeave(this);
		CImageList::EndDrag();

		ReleaseCapture();

		delete m_pDragImage;

		theTree.SelectDropTarget(NULL);
		m_htiOldDrop = NULL;

		if( m_htiDrag == m_htiDrop )
			return;

		HTREEITEM htiParent = m_htiDrop;
		while( (htiParent = theTree.GetParentItem(htiParent)) != NULL )
		{
			if( htiParent == m_htiDrag ) return;
		}

		theTree.Expand( m_htiDrop, TVE_EXPAND );

		HTREEITEM htiNew = CopyBranch( m_htiDrag, m_htiDrop, TVI_LAST );
		theTree.DeleteItem(m_htiDrag);
		theTree.SelectItem( htiNew );

		if( m_idTimer )
		{
			KillTimer( m_idTimer );
			m_idTimer = 0;
		}
	}
}

void CDragView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CTreeView::OnMouseMove(nFlags, point);

	HTREEITEM hti;
	UINT      flags;

	if( m_bLDragging )
	{
		CTreeCtrl& theTree = GetTreeCtrl();
		POINT pt = point;
		ClientToScreen( &pt );
		CImageList::DragMove(pt);
		
		hti = theTree.HitTest(point,&flags);
		if( hti != NULL )
		{
			CImageList::DragShowNolock(FALSE);

			if( m_htiOldDrop == NULL )
				m_htiOldDrop = theTree.GetDropHilightItem();

			theTree.SelectDropTarget(hti);
			
			m_htiDrop = hti;
			
			if( m_idTimer && hti == m_htiOldDrop )
			{
				KillTimer( m_idTimer );
				m_idTimer = 0;
			}
			
			if( !m_idTimer )
				m_idTimer = SetTimer( 1000, 2000, NULL );

			CImageList::DragShowNolock(TRUE);
		}
	}
}

HTREEITEM CDragView::CopyItem
	(
		HTREEITEM hti,
		HTREEITEM htiNewParent,
		HTREEITEM htiAfter // = TVI_LAST
	)
{
	CTreeCtrl& theTree = GetTreeCtrl();

	TVINSERTSTRUCT insert;
	::ZeroMemory(&insert, sizeof(TVINSERTSTRUCT));

	HTREEITEM htiNew = NULL;
	CString text;

	insert.item.hItem = hti;
	insert.item.mask = TVIF_CHILDREN|TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
	theTree.GetItem(&(insert.item));
	text = theTree.GetItemText( hti );

	insert.item.cchTextMax = text.GetLength();
	insert.item.pszText = text.LockBuffer();

	insert.hParent = htiNewParent;
	insert.hInsertAfter = htiAfter;
	insert.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
	htiNew = theTree.InsertItem(&insert);
	text.UnlockBuffer();

	theTree.SetItemData( htiNew, theTree.GetItemData( hti ) );
	theTree.SetItemState( htiNew, theTree.GetItemState( hti, TVIS_STATEIMAGEMASK ), TVIS_STATEIMAGEMASK );

	return htiNew;
}

HTREEITEM CDragView::CopyBranch
	(
		HTREEITEM hti,
		HTREEITEM htiNewParent,
		HTREEITEM htiAfter // = TVI_LAST
	)
{
	CTreeCtrl& theTree = GetTreeCtrl();

	HTREEITEM htiChild = NULL;

	HTREEITEM htiNew = CopyItem( hti, htiNewParent, htiAfter );
	htiChild = theTree.GetChildItem( hti );
	while( htiChild != NULL )
	{
		CopyBranch( htiChild, htiNew );
		htiChild = theTree.GetNextSiblingItem( htiChild );
	}

	return htiNew;
}

void CDragView::OnDestroy() 
{
	CImageList* pImage = GetTreeCtrl().GetImageList( TVSIL_NORMAL );
	delete pImage;

	if( m_idTimer )
	{
		KillTimer( m_idTimer );
		m_idTimer = 0;
	}

	CTreeView::OnDestroy();
}

void CDragView::OnTimer(UINT nIDEvent) 
{
	if( nIDEvent == m_idTimer )
	{
		CTreeCtrl& theTree = GetTreeCtrl();
		HTREEITEM htiFloat = theTree.GetDropHilightItem();
		if( htiFloat && htiFloat == m_htiDrop )
		{
			if( theTree.ItemHasChildren( htiFloat ) )
				theTree.Expand( htiFloat, TVE_EXPAND );
		}
	}

	CTreeView::OnTimer(nIDEvent);
}